#pragma once

#ifndef Vector3D_H
#define Vector3D_H

#include "MyMath.h"
#include <iostream>

#pragma warning( disable: 4290 ) //for throw(DivideByZero)

struct Vector3D
{
	float x, y, z;
	bool IsEqual(float a, float b) const;

	Vector3D(float a = 0.0, float b = 0.0, float c = 0.0);
	Vector3D(const Vector3D &rhs);
	~Vector3D();

	void Set(float a = 0, float b = 0, float c = 0); //Set all data
	void SetZero(void); //Set all data to zero
	bool IsZero(void) const; //Check if data is zero

	Vector3D operator+(const Vector3D& rhs) const; //Vector addition
	Vector3D& operator+=(const Vector3D& rhs);

	Vector3D operator-(const Vector3D& rhs) const; //Vector subtraction
	Vector3D& operator-=(const Vector3D& rhs);

	Vector3D operator-(void) const; //Unary negation

	Vector3D operator*(float scalar) const; //Scalar multiplication
	Vector3D& operator*=(float scalar);

	bool operator==(const Vector3D& rhs) const; //Equality check
	bool operator!= (const Vector3D& rhs) const; //Inequality check

	Vector3D& operator=(const Vector3D& rhs); //Assignment operator

	float Length(void) const; //Get magnitude
	float LengthSquared(void) const; //Get square of magnitude

	float Dot(const Vector3D& rhs) const; //Dot product
	Vector3D Cross(const Vector3D& rhs) const; //Cross product

	//Return a copy of this vector, normalized
	//Throw a divide by zero exception if normalizing a zero vector
	Vector3D Normalized(void) const throw(DivideByZero);

	//Normalize this vector and return a reference to it
	//Throw a divide by zero exception if normalizing a zero vector
	Vector3D& Normalize(void) throw(DivideByZero);

	friend std::ostream& operator<<(std::ostream& os, Vector3D& rhs); //print to ostream

	friend Vector3D operator*(float scalar, const Vector3D& rhs); //what is this for?
};

#endif //Vector3D_H

//#pragma once
//
//#include <math.h>
//
//class Vector3D
//{
//public:
//	float x, y, z;
//
//	//default constructor
//	Vector3D(float X = 0, float Y = 0, float Z = 0)
//	{
//		x = X;
//		y = Y;
//		z = Z;
//	}
//	~Vector3D(){};
//
//	void Set(float X = 0.0, float Y = 0.0, float Z = 0.0)
//	{
//		x = X;
//		y = Y;
//		z = Z;
//	}
//
//
//	//calculate and return the magnitude of this vector
//	float GetMagnitude()
//	{
//		return sqrtf(x * x + y * y + z * z);
//	}
//
//	//multiply this vector by a scalar
//	Vector3D operator*(float num) const
//	{
//		return Vector3D(x * num, y * num, z * num);
//	}
//
//	//pass in a vector, pass in a scalar, return the product
//	friend Vector3D operator*(float num, Vector3D const &vec)
//	{
//		return Vector3D(vec.x * num, vec.y * num, vec.z * num);
//	}
//
//	//add two vectors
//	Vector3D operator+(const Vector3D &vec) const
//	{
//		return Vector3D(x + vec.x, y + vec.y, z + vec.z);
//	}
//
//	//subtract two vectors
//	Vector3D operator-(const Vector3D &vec) const
//	{
//		return Vector3D(x - vec.x, y - vec.y, z - vec.z);
//	}
//
//	//normalize this vector
//	void normalizeVector3D()
//	{
//		float magnitude = sqrtf(x * x + y * y + z * z);
//		x /= magnitude;
//		y /= magnitude;
//		z /= magnitude;
//	}
//
//	// returns the normalized version of this vector
//	Vector3D normalized()
//	{
//		return  Vector3D(x / GetMagnitude(), y / GetMagnitude(), z / GetMagnitude());
//	}
//
//	//calculate and return dot product
//	float dotVector3D(const Vector3D &vec) const
//	{
//		return x * vec.x + y * vec.y + z * vec.z;
//	}
//
//	//calculate and return cross product
//	Vector3D crossVector3D(const Vector3D &vec) const
//	{
//		return Vector3D(y * vec.z - z * vec.y,
//			z * vec.x - x * vec.z,
//			x * vec.y - y * vec.x);
//	}
//};

